package com.cc.order.service;

import com.cc.order.feign.ItemFeign;
import com.cc.order.model.Item;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

/**
 * @Description: 用一句话描述
 * @Auther: 新梦想*陈超
 * @Date: 2021/8/2 16:47
 */
@Service
public class ItemService {

    @Autowired
    private RestTemplate restTemplate;

    @Value("${item.service.url}")
    private String itemUrl;

    public Item queryItemById(Long id) {
        /*
          订单微服务调用商品微服务的根据id查询商品的接口  (item-service服务的ItemController#item/{id})
          1.浏览器(网络服务)：http://localhost:8080/item/3
          2.通过Java实现仿浏览器(rpc)：1)socket 2)httpClient,Netty 3)dubbo  4) (spring)RestTemplate(httpClient)
             RestTemplate类：Spring框架对RESTful方式的http请求做了封装(底层HttpClient)，来简化操作
          问题：1.微服务架构---一定是集群模式(多个商品服务服务器)，而这里通过写IP永远只能访问某个商品微服务
         */
        //TODO RPC调用方式一：Ip+端口
//        Item item = restTemplate.getForObject( itemUrl+ id, Item.class);

        //TODO RPC调用方式二：服务名称  （2个女朋友----决策(负载均衡：Ribbon--(随机，投票，LRU....)):石头剪刀---->来一个女朋友陪我逛街)
        String itemUrl = "http://item-service/item/" + id;
        Item item = restTemplate.getForObject(itemUrl, Item.class);
        return item;
    }

    /**
     * 3秒钟内，请求次数达到 2 个，并且失败率在 50%以上，就跳闸
     * 跳闸后的活动窗口设置为 3 秒
     *
     * @param
     * @return
     */
    @HystrixCommand(fallbackMethod = "queryItemByIdFallbackMethod"
            ,commandProperties = {
//            @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value = "2000"), //服务降级超时时间为 2秒
            @HystrixProperty(name = "metrics.rollingStats.timeInMilliseconds", value = "3000"),//活动窗口3秒钟内
            @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "2"),//2个请求
            @HystrixProperty(name = "circuitBreaker.errorThresholdPercentage", value = "50"),//失败率 50%
            @HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds", value = "3000")//跳闸后活动窗口 3s
    })
//    @HystrixCommand
    public Item queryItemById2(Long id) {
        String itemUrl = "http://item-service/item/" + id;
        Item item = restTemplate.getForObject(itemUrl, Item.class);
        System.out.println("===========HystrixCommand queryItemById-线程池名称：" + Thread.currentThread().getName() + "订单系统调用商品服务,result:" + item);
        return item;
    }

    /*
      远程调用使用spring cloud open feign进行远程调用(RPC)
     */
    @Autowired
    private ItemFeign itemFeign;

    @HystrixCommand(fallbackMethod = "queryItemByIdFallbackMethod",
            commandProperties = {
            @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value = "2000"), //服务降级超时时间为 2秒
            @HystrixProperty(name = "metrics.rollingStats.timeInMilliseconds", value = "3000"),//活动窗口3秒钟内
            @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "2"),//2个请求
            @HystrixProperty(name = "circuitBreaker.errorThresholdPercentage", value = "50"),//失败率 50%
            @HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds", value = "3000")}//跳闸后活动窗口 3s
             )
    public Item queryItemById3(Long id) {
        Item item = itemFeign.queryItemById(id);
        System.out.println("===========HystrixCommand queryItemById-线程池名称：" + Thread.currentThread().getName() + "订单系统调用商品服务,result:" + item);
        return item;
    }


    /**
     * 请求失败执行的方法
     * fallbackMethod的方法参数个数类型要和原方法一致
     *
     * @param id
     * @return
     */
    public Item queryItemByIdFallbackMethod(Long id) {
        return new Item(id, "查询商品信息出错!", null, null, null);
    }

}

